package com.sugon.modules.kpi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.sugon.dao.MesStoplineDao;
import com.sugon.modules.analyse.consts.KpiTarget;
import com.sugon.modules.analyse.model.chart.KpiTargetBarEchartOptionDataVO;
import com.sugon.modules.analyse.model.vo.DeviceKpiStatParamVO;
import com.sugon.modules.kpi.model.StopLineStatVO;
import com.sugon.modules.kpi.service.IKpiTargetComputor;
import com.sugon.modules.report.service.IShiftProjectManager;
import com.sugon.modules.utils.MapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author ： YuXD
 * @description： 设备开动率KPI计算器实现类
 * 计算公式：1-（故障时间/实际生产时间）
 * 故障时间 = 故障维修工单的时间
 * 实际生产时间（包含故障时间，不包含非故障停机时间
 * @date ： 2020-11-15 下午 3:27
 * @version: 1.0
 */
@Service
public class SBKDLKPIComputorImpl implements IKpiTargetComputor {

    @Autowired
    private MesStoplineDao mesStoplineDao;
    @Autowired
    private IShiftProjectManager shiftProjectManager;

    /**
     * compute
     *
     * @param kpiStatParam kpi统计参数
     * @return
     */
    @Override
    public KpiTargetBarEchartOptionDataVO compute(DeviceKpiStatParamVO kpiStatParam) {
        KpiTargetBarEchartOptionDataVO kpiTargetBarEchartOption = new KpiTargetBarEchartOptionDataVO();
        // 根据不同的设备组织级别统计出不同的MTTR原始数据
        KpiTarget kpiTarget = getType();
        Assert.isTrue(kpiStatParam.getLevel() >= kpiTarget.getLevel(), "不支持当前设备组织[" + kpiTarget.getLabel() + "]维度的KPI计算！");
        // 获取设备故障停机次数和时长统计
        Map<Integer, StopLineStatVO> mttrStatMap = getDeviceFaultStopHourTotalStat(kpiStatParam);
        // 获取排班时长统计数据
        Map<Integer, Double> shiftHourTotalStatMap = shiftProjectManager.doYearlyLineShiftStat(kpiStatParam);
        // 当前月份
        Integer currentMonth = com.sugon.modules.utils.DateUtil.month(null);
        // 待统计的年份
        Integer statYearly = kpiStatParam.getYearly();
        // 今年年份
        int thisYear = DateUtil.thisYear();
        for (int i = 1; i <= 12; i++) {
            // 年份没到或者月份没到的一律默认为0
            if ((statYearly > thisYear) || (statYearly == thisYear && i > currentMonth)) {
                kpiTargetBarEchartOption.add(0.0);
            } else {
                Double shiftAccuStat = MapUtil.getDouble(shiftHourTotalStatMap, i, 0);
                // 如果当月设备没有发生故障，那么开动率为100%
                StopLineStatVO stopLineStat = mttrStatMap.get(i);
                /*
                    如果开动率时间为0，那么开动率为0
                    如果当月没有故障统计，且排班时间不为0，那么开动率为100%
                    否则，按照计算设备开动率： [1-（故障时间/实际生产时间）]计算即可
                 */
                if (shiftAccuStat == null || shiftAccuStat == 0) {
                    kpiTargetBarEchartOption.add(0.0);
                } else if (stopLineStat == null) {
                    kpiTargetBarEchartOption.add(100.0);
                } else {
                    // 计算设备开动率： 1-（故障时间/实际生产时间）
                    Double deviceWorkRate = 1 - NumberUtil.div(stopLineStat.getMinuteTotal(), shiftAccuStat, 4, RoundingMode.HALF_UP);
                    kpiTargetBarEchartOption.add(deviceWorkRate * 100);
                }
            }
        }
        return kpiTargetBarEchartOption;
    }

    /**
     * 获取设备的停机次数时长月度统计
     *
     * @param kpiStatParam
     * @return
     */
    private Map<Integer, StopLineStatVO> getDeviceFaultStopHourTotalStat(DeviceKpiStatParamVO kpiStatParam) {
        List<StopLineStatVO> mttrRootData = mesStoplineDao.doMonthlyStopDeviceStat(kpiStatParam.getYearly(), CollectionUtil.newArrayList(kpiStatParam.getDeviceOrganizationCode()));
        if (mttrRootData == null) {
            mttrRootData = new ArrayList<>();
        }
        return mttrRootData.stream().collect(Collectors.toMap(StopLineStatVO::getMonth, account -> account));
    }

    /**
     * getType
     *
     * @return
     */
    @Override
    public KpiTarget getType() {
        return KpiTarget.SBKDL;
    }

}
